import { Config } from "@/entities/Config";
import { Dataset } from "@/entities/Dataset";
import { Endpoint } from "@/entities/Endpoint";
import { initORM } from "@/utils";
import { NextApiRequest, NextApiResponse } from "next";
import { getCurrentUser } from "./user";
import { getApp, getUserListOfApp } from "./app";
import { User } from "@/entities/User";
import { App } from "@/entities/App";
import { pickData, sleep } from "@/utils/base";
import { getDataset } from "./dataset";

export async function getEndpoints(req: NextApiRequest) {
  const em = await initORM();
  const query = req.query ?? {};
  const conditions = {
    ...(query.datasetid ? { dataset: { id: Number(query.datasetid) } } : {}),
    ...(query.name ? { name: { $like: `%${query.name}%` } } : {}),
    ...(query.disabled ? { disabled: Number(query.disabled) } : {}),
  };
  // console.log("🚀 ~ getConfigs ~ conditions:", conditions);
  const endpoints = await em.find(Endpoint, conditions, {
    populate: ["dataset", "editor"],
  });

  return {
    success: true as const,
    message: "Query Endpoints success",
    data: { endpoints },
  };
}

export async function getEndpoint(req: NextApiRequest) {
  const endpointid = req.query.endpointid || req.body?.endpointid;
  //   const curUser = await getCurrentUser(req);

  const em = await initORM();
  const endpoint = await em.findOne(Endpoint, Number(endpointid));

  if (!endpoint) {
    return {
      success: false,
      data: {},
      message: "Endpoint not found",
    };
  }

  return {
    success: true,
    data: endpoint,
    message: "Query endpoint success",
  };
}

export async function updateEndpoint(
  req: NextApiRequest,
  res: NextApiResponse<APIRes>
) {
  const { datasetid, name, disabled, introduce, app } = req.body ?? {};

  const endpointResult = await getEndpoint(req);

  if (!endpointResult.success) {
    res.status(400).json(endpointResult as APIRes);
    return;
  }

  const endpoint = endpointResult.data as Endpoint;

  const keys = ["name", "introduce", "type", "value", "isOutputCsv"] as const;

  keys.forEach((key) => {
    if (req.body[key] !== undefined) {
      Object.assign(endpoint, { [key]: req.body[key] as string });
    }
  });

  const em = await initORM();

  const curUser = await getCurrentUser(req);
  if (!curUser) {
    res.status(400).json({
      success: false,
      data: {},
      message: "User not found",
    });
  } else {
    const userRef = em.getReference(User, curUser.id, { wrapped: true });
    endpoint.editor = userRef;
  }

  await em.persistAndFlush(endpoint);

  res.status(200).json({
    success: true,
    data: endpoint,
    message: "Update endpoint success",
  });
}

export async function createEndpoint(
  req: NextApiRequest,
  res: NextApiResponse<APIRes>
) {
  const em = await initORM();
  const curUser = await getCurrentUser(req);
  if (!curUser) {
    res.status(400).json({
      success: false,
      data: {},
      message: "User not found",
    });
    return;
  }

  const curDatasetResult = await getDataset(req);
  if (!curDatasetResult.success) {
    res.status(400).json(curDatasetResult as APIRes);
    return;
  }

  const curDataset = curDatasetResult.data as App;

  const data = Object.assign({}, req.body ?? {});
  if (Array.isArray(data.value)) {
    data.value = JSON.stringify(data.value);
  }
  const endpoint = await em.create(
    Endpoint,
    Object.assign(
      { creator: curUser, editor: curUser, dataset: curDataset },
      data
    )
  );
  await em.persistAndFlush(endpoint);
  await sleep(1);

  res.status(200).json({
    success: true,
    data: pickData(endpoint, ["id", "name"]),
    message: "Endpoint created",
  });
}

export async function delEndpoint(
  req: NextApiRequest,
  res: NextApiResponse<APIRes>
) {
  const endpointid = req.query.endpointid || req.body?.endpointid;
  //   const curUser = await getCurrentUser(req);

  const em = await initORM();
  const endpoint = await em.findOne(Endpoint, Number(endpointid));

  if (!endpoint) {
    return {
      success: false,
      data: {},
      message: "Endpoint not found",
    };
  }

  await em.removeAndFlush(endpoint);

  res.status(200).json({
    success: true,
    data: pickData(endpoint, ["id", "name"]),
    message: "Endpoint deleted",
  });
}
